package com.zijidelu.luframework.domain.model.aggregate;

import com.zijidelu.luframework.base.model.DataModel;
import com.zijidelu.luframework.domain.exception.DomainException;
import com.zijidelu.luframework.domain.model.entity.Entity;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;

import java.util.UUID;

/**
 * 基础聚合根。
 * <p>
 * 聚合根只对对应的领域实体进行操作，生产的领域实体交由领域服务或仓库持久化。
 *`
 * @author ZIJIDELU
 * @datetime 2025/10/17 10:54
 */
@Slf4j
@ToString
@Getter
@EqualsAndHashCode(callSuper = true)
public abstract class AggregateRoot<D extends DataModel, E extends Entity<D>>
        extends AbstractCrudAggregateRoot<D, E> implements AggregateRootLifeCycle {

    /**
     * 聚合根ID
     * <p>
     * 非数据库实体ID，用于聚合根的业务追踪审计
     */
    private final String id = UUID.randomUUID().toString();

    public AggregateRoot(E entity) {
        super(entity);
    }

    /**
     * 获取聚合根类型名称
     *
     * <p>用于日志记录和事件发布</p>
     *
     * @return 聚合根类型名称（类名）
     */
    public String getRootType() {
        return getClass().getSimpleName();
    }

    /**
     * 初始化聚合根
     *
     * <p>在聚合根创建时调用此方法初始化状态</p>
     */
    protected abstract void doInitialize();

    @Override
    public void initialize() {
        try {
            log.debug("AggregateRoot initialize | type={} | id={}", getRootType(), getId());
            doInitialize();
            log.debug("AggregateRoot initialized Successfully | type={} | id={}", getRootType(), getId());
        } catch (Exception e) {
            log.error("AggregateRoot initialize Failed | type={} | id={}", getRootType(), getId(), e);
            throw new DomainException("AggregateRoot initialize Failed", e);
        }
    }

    /**
     * 销毁聚合根
     *
     * <p>在聚合根生命周期结束时调用此方法</p>
     */
    protected void doDestroy() {
    }

    @Override
    public void destroy() {
        try {
            log.debug("AggregateRoot destroy | type={} | id={}", getRootType(), getId());
            doDestroy();
            clearDomainEvents();
            clearChildrenEntityVault();
            log.debug("AggregateRoot destroyed Successfully | type={} | id={}", getRootType(), getId());
        } catch (Exception e) {
            log.error("AggregateRoot destroy Failed | type={} | id={}", getRootType(), getId(), e);
            throw new DomainException("AggregateRoot destroy Failed", e);
        }
    }

}
